package com.billdowney.util.encrypt;

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

/**
 * AES加密解密工具类
 * 
 * @author 超级小富翁 - BillDowney
 * @data 2017年8月17日 下午7:30:58
 */
public class AESUtil {

	private static final String KEY_ALGORITHM = "AES";
	private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";// 默认的加密算法

	/**
	 * @Function: encryptByBase64
	 * @Description: 执行base64加密操作
	 * @param content
	 *            需要加密的内容
	 * @param secretKey
	 *            秘钥
	 * @return 通过base64加密过后的内容，加密失败返回null
	 * @author: 超级小富翁 - BillDowney
	 * @throws Exception 
	 * @date: 2018年1月15日 下午3:34:01
	 */
	public static String encryptByBase64(String content, String secretKey) throws Exception {
		return Base64.encodeBase64String(encryptByByteArray(content, secretKey));// 通过Base64转码返回
	}

	/**
	 * @Function: decryptByBase64
	 * @Description: 执行base64解密操作
	 * @param content
	 *            加密过后的内容
	 * @param secretKey
	 *            秘钥
	 * @return 解密过后的内容，解密失败返回null
	 * @author: 超级小富翁 - BillDowney
	 * @throws Exception 
	 * @date: 2018年1月15日 下午3:34:40
	 */
	public static String decryptByBase64(String content, String secretKey) throws Exception {
		return decryptByByteArray(Base64.decodeBase64(content), secretKey);
	}

	/**
	 * @Function: encryptByHex
	 * @Description: 执行16进制加密
	 * @param content
	 *            需要加密的内容
	 * @param secretKey
	 *            秘钥
	 * @return 通过base64加密过后的内容，加密失败返回null
	 * @author: 超级小富翁 - BillDowney
	 * @throws Exception 
	 * @date: 2018年1月15日 下午3:46:18
	 */
	public static String encryptByHex(String content, String secretKey) throws Exception {
		return Hex.encodeHexString(encryptByByteArray(content, secretKey));
	}

	/**
	 * @Function: decryptByHex
	 * @Description: 执行16进制解密
	 * @param content
	 *            加密过后的内容
	 * @param secretKey
	 *            秘钥
	 * @return 解密过后的内容
	 * @author: 超级小富翁 - BillDowney
	 * @throws Exception 
	 * @date: 2018年1月15日 下午3:47:32
	 */
	public static String decryptByHex(String content, String secretKey) throws Exception {
		return decryptByByteArray(Hex.decodeHex(content), secretKey);
	}

	/**
	 * @Function: encryptByByteArray
	 * @Description: 加密获取byte数组
	 * @param content
	 *            加密内容
	 * @param secretKey
	 *            加密秘钥
	 * @return 加密过后的byte数组
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月15日 下午3:30:16
	 */
	public static byte[] encryptByByteArray(String content, String secretKey) throws Exception {
		Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);// 创建密码器
		byte[] byteContent = content.getBytes("utf-8");
		cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(secretKey));// 初始化为加密模式的密码器
		return cipher.doFinal(byteContent);// 加密
	}

	/**
	 * @Function: decryptByByteArray
	 * @Description: 解密获取内容
	 * @param content
	 *            加密的内容
	 * @param secretKey
	 * @return
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月15日 下午3:31:47
	 */
	public static String decryptByByteArray(byte[] content, String secretKey) throws Exception {
		// 实例化
		Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
		// 使用密钥初始化，设置为解密模式
		cipher.init(Cipher.DECRYPT_MODE, getSecretKey(secretKey));
		// 执行操作
		return new String(cipher.doFinal(content), "utf-8");
	}

	/**
	 * @Function: getSecretKey
	 * @Description: 秘钥生成器
	 * @param password
	 *            秘钥
	 * @return
	 * @author: 超级小富翁 - BillDowney
	 * @date: 2018年1月15日 下午3:31:11
	 */
	private static SecretKeySpec getSecretKey(final String password) {
		// 返回生成指定算法密钥生成器的 KeyGenerator 对象
		KeyGenerator kg = null;
		try {
			kg = KeyGenerator.getInstance(KEY_ALGORITHM);
			// AES 要求密钥长度为 128
			kg.init(128, new SecureRandom(password.getBytes()));
			// 生成一个密钥
			SecretKey secretKey = kg.generateKey();
			return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥
		} catch (NoSuchAlgorithmException ex) {
			ex.printStackTrace();
		}
		return null;
	}

}
